home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dc1 / stmt.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  22KB  |  969 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  STMT.C
  9.  *
  10.  *  Parse procedural junk: declarations, statements, etc...
  11.  */
  12.  
  13. /*
  14. **      $Filename: stmt.c $
  15. **      $Author: dice $
  16. **      $Revision: 30.152 $
  17. **      $Date: 1995/01/08 22:30:25 $
  18. **      $Log: stmt.c,v $
  19.  * Revision 30.152  1995/01/08  22:30:25  dice
  20.  *  test message
  21.  *
  22.  * Revision 30.5  1994/06/13  18:37:37  dice
  23.  * .
  24.  *
  25.  * Revision 30.0  1994/06/10  18:04:57  dice
  26.  * .
  27.  *
  28.  * Revision 1.8  1994/04/15  21:18:54  jtoebes
  29.  * Handle labels before the start of a case clause properly.
  30.  *
  31.  * Revision 1.7  1993/10/17  04:03:38  jtoebes
  32.  * Eliminate compiler warning about unused variable.
  33.  *
  34.  * Revision 1.6  1993/10/15  22:44:24  jtoebes
  35.  * Eliminated old code which called cerror.
  36.  *
  37.  * Revision 1.5  1993/09/19  13:14:10  jtoebes
  38.  * Fixed BUG00148 - Compiler does not catch gotos to non-existent label.
  39.  * Changed intermediate gotolabel information to know more about the label.
  40.  * Also added code to identify when more than one label has been entered.
  41.  *
  42.  * Revision 1.4  1993/09/11  16:12:41  jtoebes
  43.  * Fixed BUG01010 - Code not allowed in switch statement before the first case.
  44.  * Added code to catch the code before the first case statement and store it
  45.  * to be emitted later.
  46.  *
  47.  * Revision 1.3  1993/09/06  22:18:01  jtoebes
  48.  * Fixed BUG06004 - DC1 fails to detect reuse of a register in a function parameter
  49.  * list.
  50.  *
  51. **/
  52.  
  53. #include "defs.h"
  54.  
  55. Prototype short CompProcedureArgDeclarators(short, Var ***, long *, long *);
  56. Prototype short CompProcedure(short, Var *);
  57. Prototype short CompStmtDeclExp(short, Stmt **, long);
  58. Prototype short CompBlock(short, Stmt **);
  59. Prototype short CompFor(short, Stmt **);
  60. Prototype short CompWhile(short, Stmt **);
  61. Prototype short CompDo(short, Stmt **);
  62. Prototype short CompIf(short, Stmt **);
  63. Prototype short CompSwitch(short, Stmt **);
  64. Prototype short CompBreak(short, Stmt **);
  65. Prototype short CompContinue(short, Stmt **);
  66. Prototype short CompGoto(short, Stmt **);
  67. Prototype short CompLabel(short, Stmt **);
  68. Prototype short CompReturn(short, Stmt **);
  69. Prototype short CompBreakPoint(short, Stmt **);
  70.  
  71. /*
  72.  *  Deals with argument declarations to a procedure.  Does NOT compile
  73.  *  the procedure itself.
  74.  *
  75.  *  Determines registerization, if any, for both externs and procedure
  76.  *  definitions.
  77.  *
  78.  * void foo ( {START} a, b, c, d )   <more>
  79.  * void foo ( {START} short, short)   <more>
  80.  * void foo ( {START} short a, short b)  <more>
  81.  *
  82.  *  more =  old style declarators (which I like much better than proto style anyway),
  83.  *        optional .. could be ';' if just a prototype.  If a procedure
  84.  *        definition then returns TokSemi.
  85.  */
  86.  
  87. short
  88. CompProcedureArgDeclarators(short t, Var ***pvars, long *pargs, long *pflags)
  89. {
  90.     Var **vars = NULL;
  91.     short i;
  92.     short n = -1;
  93.     short siz = 0;
  94.     short oldState = State;
  95.  
  96.     State = SARG;
  97.  
  98.     *pargs = 0;
  99.     *pvars = NULL;
  100.     *pflags = 0;
  101.  
  102.     if (t == TokDotDotDot) {
  103.     *pflags |= TF_DOTDOTDOT | TF_PROTOTYPE;
  104.     t = GetToken();
  105.     if (t != TokRParen)
  106.         zerror(EERROR_SYNTAX_ERROR_DECL);
  107.     n = 0;
  108.     }
  109.  
  110.     while (t != TokRParen) {
  111.     Type *baseType;
  112.     Type *type;
  113.     Var *var;
  114.     Symbol *sym = NULL;
  115.     long baseFlags;
  116.     long regFlags;
  117.  
  118.     if (n < 0)
  119.         n = 0;
  120.  
  121.     /*
  122.      *  If not an ID we assume it is a type declaration and thus this
  123.      *  is a prototype.
  124.      */
  125.  
  126.     if (t != TokId && t != TokVarId && t != TokEnumConst)
  127.         *pflags |= TF_PROTOTYPE;
  128.  
  129.     t = CompType(t, &baseType, &baseFlags, ®Flags);    /*  defaults to int if none */
  130.     type = baseType;
  131.     t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  132.     if (regFlags & RF_REGISTER)
  133.     {
  134.         int i;
  135.  
  136.         *pflags |= TF_REGCALL;
  137.         /* Ensure that the register is not used by any other parameter */
  138.         for(i = 0; i < n; i++)
  139.         {
  140.         if (vars[i]->RegFlags == regFlags)
  141.         {
  142.                 zerror(EERROR_ILLEGAL_REGSPEC);
  143.             regFlags = 0;
  144.         }
  145.         }
  146.     }
  147.  
  148.     if (type == &VoidType) {
  149.         if (n)
  150.         zerror(EERROR_SYNTAX_ERROR_DECL);
  151.         if (t != TokRParen)
  152.         zerror(EERROR_SYNTAX_ERROR_DECL);
  153.         break;
  154.     }
  155.  
  156.     if (n == siz) {
  157.         siz += 4;
  158.         vars = zrealloc(vars, sizeof(Var *), n, siz);
  159.     }
  160.  
  161.     /*
  162.      *  argument
  163.      */
  164.  
  165.     var = AllocStructure(Var);
  166.     var->Type = type;
  167.     var->Sym  = sym;
  168.     var->Flags = (baseFlags & TF_STORQUALMASK) | type->Flags | (VF_ARG | TF_AUTO);
  169.     var->RegFlags = regFlags;
  170.  
  171.     if (type->Id != TID_INT && type->Id != TID_PTR && type->Id != TID_ARY)
  172.         *pflags |= TF_STKCALL;
  173.  
  174.     if (baseFlags & (TF_STATIC|TF_EXTERN))
  175.         zerror(EERROR_ILLEGAL_QUALIFIER);
  176.  
  177.     /*
  178.      *  Bump the refs for the 'register' keyword to give the variable
  179.      *  a better chance of being put in a register.
  180.      */
  181.  
  182.     if (var->Flags & TF_REGISTER)
  183.         ++var->Refs;
  184.  
  185.     vars[n++] = var;
  186.  
  187.     if (t != TokRParen && t != TokComma) {
  188.         zerror(EERROR_SYNTAX_ERROR_DECL);
  189.         goto bad;
  190.     }
  191.     if (t == TokComma) {
  192.         t = GetToken();
  193.         if (t == TokDotDotDot) {
  194.         *pflags |= TF_DOTDOTDOT;
  195.         t = GetToken();
  196.         if (t != TokRParen)
  197.             zerror(EERROR_SYNTAX_ERROR_DECL);
  198.         }
  199.     }
  200.     }
  201.     *pargs = n;
  202.     *pvars = vars;
  203.  
  204.     /*
  205.      *    have right paren, now is this a real procedure or just a declaration
  206.      *    of some sort?
  207.      */
  208.  
  209.     t = GetToken();
  210.  
  211.     if (t == TokComma || t == TokEq || t == TokSemi || t == TokRParen) {
  212.     if (!(*pflags & TF_PROTOTYPE))
  213.         *pflags |= TF_STKCALL;
  214.     goto skip;
  215.     }
  216.  
  217.     /*
  218.      *    Else a real procedure.. handle old-style argument decls.  We return
  219.      *    when we get a '{'.  Also make sure all the variables are named.
  220.      */
  221.  
  222.     for (i = 0; i < n; ++i) {
  223.     Var *var = vars[i];
  224.  
  225.     if (var->Sym == NULL) {
  226.         zerror(EERROR_ID_MISSING_PROC);
  227.         var->Sym = MakeSymbol("____dummy", 9, TokId, 0);
  228.         /* goto bad; */
  229.         /* break; */
  230.     }
  231.     }
  232.  
  233.     while (t != TokLBrace) {
  234.     Type *baseType;
  235.     Type *type;
  236.     Var *var = NULL;
  237.     Symbol *sym = NULL;    /*  XXX needed? */
  238.     long  baseFlags;
  239.     long  regFlags;
  240.     long  li = LFBase->lf_Index;
  241.  
  242.     t = CompType(t, &baseType, &baseFlags, ®Flags);     /*  defaults to int if none */
  243.  
  244.     for (;;) {
  245.         type = baseType;
  246.         t = CompTypeDeclarators(t, &type, &sym, baseFlags);
  247.  
  248.         for (i = 0; i < n; ++i) {
  249.         var = vars[i];
  250.         if (var->Sym == sym)
  251.             break;
  252.         }
  253.         if (i == n) {
  254.         zerror(EERROR_ID_NOT_IN_LIST);
  255.         } else {
  256.         var->Type = type;
  257.         var->Flags = (baseFlags & TF_STORQUALMASK) | type->Flags | (VF_ARG | TF_AUTO);
  258.         var->RegFlags = regFlags;
  259.         if (var->Flags & TF_REGISTER)
  260.             ++var->Refs;
  261.         if (regFlags & RF_REGISTER)
  262.             *pflags |= TF_REGCALL;
  263.         }
  264.         if (type->Id != TID_INT && type->Id != TID_PTR && type->Id != TID_ARY)
  265.         *pflags |= TF_STKCALL;
  266.  
  267.         if (t == TokComma) {
  268.         t = GetToken();
  269.         continue;
  270.         }
  271.         break;
  272.     }
  273.     if (t != TokSemi) {
  274.         zerror(EERROR_EXPECTED_SEMICOLON);
  275.         if (li == LFBase->lf_Index)     /*    prevent inifinite loop    */
  276.         t = GetToken();
  277.         break;
  278.     }
  279.     t = GetToken();
  280.     }
  281.  
  282. skip:
  283.  
  284.     /*
  285.      *    If explicitly registerized then clear TF_STKCALL bit (which gets
  286.      *    set when automatic registerization is not possible)
  287.      */
  288.  
  289.     if (*pflags & TF_REGCALL)
  290.     *pflags &= ~TF_STKCALL;
  291.  
  292. bad:
  293.     State = oldState;
  294.     return(t);
  295. }
  296.  
  297. /*
  298.  *  Compiles a procedure, t had better be TokLBrace.
  299.  *
  300.  *  returns TokSemi to simply toplevel.c
  301.  *
  302.  *  Normally assigns in decls work as follows:    the variable is added to the
  303.  *  current block's variable list and the decl-stmt is added to the current
  304.  *  block's statement list (which retains placement).
  305.  */
  306.  
  307. short
  308. CompProcedure(short t, Var *var)
  309. {
  310.     Stmt *stmt;
  311.     short oldState = State;
  312.     long lexIdx = LFBase->lf_Index;
  313.  
  314.     if (t != TokLBrace)
  315.     zerror(EERROR_EXPECTED_OCBRACE_PROC);
  316.  
  317.     State = SARG;        /*    first properly add args */
  318.     var->u.Block = BlockDown(BT_PROC);
  319.  
  320.     {
  321.     short i;
  322.     Type *type = var->Type;
  323.  
  324.     for (i = 0; i < type->Args; ++i) {
  325.         Var *xvar = type->Vars[i];
  326.  
  327.         BlockAddVar(xvar);
  328.         Assert(xvar->Sym);
  329.         SemanticAdd(xvar->Sym, TokVarId, xvar);
  330.     }
  331.     }
  332.  
  333.     State = SINSIDE;
  334.     t = CompBlock(GetToken(), &stmt);
  335.     BlockAddStmt(stmt);
  336.  
  337.     State = SARG;
  338.     BlockUp();
  339.     State = SOUTSIDE;
  340.  
  341.     /*
  342.      *    t should be TokRBrace.. return TokSemi instead
  343.      */
  344.  
  345.     if (t != TokRBrace)
  346.     yerror(lexIdx, EERROR_EXPECTED_OCBRACE_PROC);
  347.  
  348.     State = oldState;
  349.     return(TokSemi);
  350. }
  351.  
  352. short
  353. CompStmtDeclExp(short t, Stmt **pstmt, long semiexp)
  354. {
  355.     *pstmt = NULL;
  356.  
  357.     switch(t) {
  358.     case TokLBrace:
  359.     t = CompBlock(GetToken(), pstmt);
  360.     t = GetToken();
  361.     break;
  362.     case TokBreak:
  363.     t = CompBreak(GetToken(), pstmt);
  364.     break;
  365.     case TokCase:
  366.     zerror(EERROR_CASE_DEFAULT_OUTSIDE);
  367.     t = GetToken();
  368.     break;
  369.     case TokContinue:
  370.     t = CompContinue(GetToken(), pstmt);
  371.     break;
  372.     case TokDefault:
  373.     zerror(EERROR_CASE_DEFAULT_OUTSIDE);
  374.     t = GetToken();
  375.     break;
  376.     case TokDo:
  377.     BlockCost += 2;
  378.     t = CompDo(GetToken(), pstmt);
  379.     BlockCost -= 2;
  380.     break;
  381.     case TokElse:
  382.     zerror(EERROR_ELSE_NO_IF);
  383.     t = GetToken();
  384.     break;
  385.     case TokFor:
  386.     BlockCost += 2;
  387.     t = CompFor(GetToken(), pstmt);
  388.     BlockCost -= 2;
  389.     break;
  390.     case TokGoto:
  391.     t = CompGoto(GetToken(), pstmt);
  392.     break;
  393.     case TokIf:
  394.     t = CompIf(GetToken(), pstmt);
  395.     break;
  396.     case TokReturn:
  397.     t = CompReturn(GetToken(), pstmt);
  398.     break;
  399.     case TokSwitch:
  400.     t = CompSwitch(GetToken(), pstmt);
  401.     break;
  402.     case TokWhile:
  403.     BlockCost += 2;
  404.     t = CompWhile(GetToken(), pstmt);
  405.     BlockCost -= 2;
  406.     break;
  407.     case TokBreakPoint:
  408.     t = CompBreakPoint(GetToken(), pstmt);
  409.     break;
  410.     case TokSemi:
  411.     if (semiexp)
  412.         t = GetToken();
  413.     break;
  414.  
  415.     /*
  416.      *    declaration
  417.      */
  418.  
  419.     case TokStruct:
  420.     case TokEnum:
  421.     case TokUnion:
  422.     case TokTypeQual:
  423.     case TokTypeDef:
  424.     case TokTypeId:
  425.     case TokTypeof:
  426.     {
  427.         Var *var = NULL;
  428.         BlockStmt *block = NULL;
  429.  
  430.         t = CompDecl(t, &var, semiexp);
  431.  
  432.         /*
  433.          *    add variables to the current block, any procedure decls
  434.          *    will be moved to the top level.  Returns base of list
  435.          *    of newly added variables to the current block (minus any
  436.          *    procdures added to the top)
  437.          */
  438.  
  439.         if (var)
  440.         var = BlockAddVar(var);
  441.  
  442.         if (var && var->Next)           /*  more 'n one!    */
  443.         block = BlockDown(BT_BLOCK);
  444.  
  445.         while (var) {        /*  for each...     */
  446.         if (var->Type->Id != TID_PROC && var->u.AssExp && (var->Flags & TF_AUTO)) {
  447.             ExpStmt *es = AllocTmpStructure(ExpStmt);
  448.  
  449.             es->st_Func = (void (*)(void *))GenExp;
  450.             es->st_Tok    = TokExp;
  451.             es->st_LexIdx = LFBase->lf_Index;
  452.             InsertAssign(&var->u.AssExp, var);
  453.             es->Expr = var->u.AssExp;
  454.             ++var->Refs;
  455.             if (block)
  456.             BlockAddStmt((Stmt *)es);
  457.             else
  458.             *pstmt = (Stmt *)es;
  459.         }
  460.         var = var->Next;
  461.         }
  462.         if (block) {
  463.         *pstmt = (Stmt *)block;
  464.         BlockUp();
  465.         }
  466.     }
  467.     break;
  468.     case TokLabelId:
  469.     Assert(0);
  470.     /* t = CompLabel(t, pstmt); */
  471.     break;
  472.     case TokId:     /*    label or subroutine call ?    */
  473.     case TokVarId:  /*    label or variable ?          */
  474.     if (LexHackColon) {    /*  label (lexical hack checks for a :) */
  475.         t = CompLabel(t, pstmt);
  476.         break;
  477.     }
  478.     /* fall through to exp */
  479.     default:
  480.  
  481.     {
  482.         Exp *exp = NULL;
  483.         ExpStmt *es = AllocTmpStructure(ExpStmt);
  484.         long li = LFBase->lf_Index;
  485.  
  486.         t = CompExp(t, &exp, 1);
  487.         if (semiexp) {
  488.         if (t == TokSemi) {
  489.             t = GetToken();
  490.         } else {
  491.             zerror(EWARN_EXPECTED_SEMICOLON);
  492.             if (LFBase->lf_Index == li)     /*  prevent endless loop */
  493.             t = GetToken();
  494.         }
  495.         }
  496.         if (exp == NULL)
  497.         zerror(EFATAL_SYNTAX_ERROR_EXP);
  498.  
  499.         es->st_Func = (void (*)(void *))GenExp;
  500.         es->st_Tok    = TokExp;
  501.         es->st_LexIdx = exp->ex_LexIdx;
  502.         es->Expr = exp;
  503.         *pstmt = (Stmt *)es;
  504.     }
  505.     break;
  506.     }
  507.     return(t);
  508. }
  509.  
  510. /*
  511.  *  CompBlock() works slightly differently in that it returns t = TokRBrace,
  512.  *  allowing toplevel.c to simply throw away t (makes the code easier)
  513.  *
  514.  *  All Comp*() for statements have access to their parent blocks... they
  515.  *  need not set it (it's done automatically on return) UNLESS they make
  516.  *  calls to other Comp*() statements.
  517.  *
  518.  *  Attempt to set block->LastLexIdx for debug info synchronization to just
  519.  *  before the close brace.  This does not always work perfectly (but does
  520.  *  not cause a screwup in those cases either).
  521.  */
  522.  
  523. short
  524. CompBlock(short t, Stmt **pstmt)
  525. {
  526.     BlockStmt *block = BlockDown(BT_BLOCK);
  527.  
  528.     *pstmt = (Stmt *)block;
  529.  
  530.     while (t != TokRBrace) {
  531.     Stmt *stmt;
  532.  
  533.     t = CompStmtDeclExp(t, &stmt, 1);
  534.     BlockAddStmt(stmt);
  535.     if (!t)
  536.         break;
  537.     }
  538.     BlockUp();
  539.  
  540.     return(t);
  541. }
  542.  
  543. /*
  544.  *  for (stmt ; exp; stmt) stmt
  545.  *
  546.  *  Note: The Block junk is to add another variable level allowing
  547.  *  temporary declarations within the for.. for (int i = 0; ...)
  548.  */
  549.  
  550. short
  551. CompFor(short t, Stmt **pstmt)
  552. {
  553.     ForStmt *stmt = AllocTmpStructure(ForStmt);
  554.     BlockStmt *block = BlockDown(BT_FOR);
  555.  
  556.     *pstmt = (Stmt *)block;
  557.     stmt->Block = block;
  558.     block->LabelLoop  = AllocLabel();
  559.     block->LabelTest  = AllocLabel();
  560.     block->LabelBreak = AllocLabel();
  561.  
  562.  
  563.     BlockAddStmt((Stmt *)stmt);
  564.  
  565.     stmt->st_Func = (void (*)(void *))GenFor;
  566.     stmt->st_Tok  = TokFor;
  567.     stmt->st_LexIdx = LFBase->lf_Index;
  568.     stmt->LabelBegin = AllocLabel();
  569.  
  570.     t = SkipToken(t, TokLParen);
  571.  
  572.     if (t != TokSemi)
  573.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);
  574.     t = SkipToken(t, TokSemi);
  575.     if (t != TokSemi)
  576.     t = CompStmtDeclExp(t, &stmt->Stmt2, 0);
  577.     t = SkipToken(t, TokSemi);
  578.     if (t != TokRParen)
  579.     t = CompStmtDeclExp(t, &stmt->Stmt3, 0);
  580.     t = SkipToken(t, TokRParen);
  581.     t = CompStmtDeclExp(t, &stmt->Stmt4, 1);
  582.  
  583.     if (stmt->Stmt2) {
  584.     if (stmt->Stmt2->st_Tok != TokExp)
  585.         zerror(EFATAL_STMT_COND_NOT_EXP);
  586.  
  587.     InsertBranch(&((ExpStmt *)stmt->Stmt2)->Expr, COND_T, block->LabelLoop);
  588.     }
  589.  
  590.     BlockUp();
  591.  
  592.     return(t);
  593. }
  594.  
  595. short
  596. CompWhile(short t, Stmt **pstmt)
  597. {
  598.     WhileStmt *stmt = AllocTmpStructure(WhileStmt);
  599.     BlockStmt *block = BlockDown(BT_WHILE);
  600.  
  601.     *pstmt = (Stmt *)block;
  602.     stmt->Block = block;
  603.     block->LabelLoop  = AllocLabel();
  604.     block->LabelTest  = AllocLabel();
  605.     block->LabelBreak = AllocLabel();
  606.  
  607.     BlockAddStmt((Stmt *)stmt);
  608.  
  609.     stmt->st_Func = (void (*)(void *))GenWhile;
  610.     stmt->st_Tok  = TokWhile;
  611.     stmt->st_LexIdx = LFBase->lf_Index;
  612.  
  613.     t = SkipToken(t, TokLParen);
  614.  
  615.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);
  616.     t = SkipToken(t, TokRParen);
  617.     t = CompStmtDeclExp(t, &stmt->Stmt2, 1);
  618.  
  619.     if (stmt->Stmt1->st_Tok != TokExp)
  620.     zerror(EFATAL_STMT_COND_NOT_EXP);
  621.     InsertBranch(&((ExpStmt *)stmt->Stmt1)->Expr, COND_T, block->LabelLoop);
  622.  
  623.     BlockUp();
  624.  
  625.     return(t);
  626. }
  627.  
  628. short
  629. CompDo(short t, Stmt **pstmt)
  630. {
  631.     DoStmt *stmt = AllocTmpStructure(DoStmt);
  632.     BlockStmt *block = BlockDown(BT_DO);
  633.  
  634.     *pstmt = (Stmt *)block;
  635.     stmt->Block = block;
  636.     block->LabelLoop  = AllocLabel();
  637.     block->LabelTest  = AllocLabel();
  638.     block->LabelBreak = AllocLabel();
  639.  
  640.     BlockAddStmt((Stmt *)stmt);
  641.  
  642.     stmt->st_Func = (void (*)(void *))GenDo;
  643.     stmt->st_Tok  = TokDo;
  644.     stmt->st_LexIdx = LFBase->lf_Index;
  645.  
  646.     t = CompStmtDeclExp(t, &stmt->Stmt1, 1);      /*  code    */
  647.     t = SkipToken(t, TokWhile);
  648.     t = CompStmtDeclExp(t, &stmt->Stmt2, 1);      /*  test    */
  649.  
  650.     if (stmt->Stmt2->st_Tok != TokExp)
  651.     zerror(EFATAL_STMT_COND_NOT_EXP);
  652.     InsertBranch(&((ExpStmt *)stmt->Stmt2)->Expr, COND_T, block->LabelLoop);
  653.  
  654.     BlockUp();
  655.  
  656.     return(t);
  657. }
  658.  
  659. short
  660. CompIf(short t, Stmt **pstmt)
  661. {
  662.     IfStmt *stmt = AllocTmpStructure(IfStmt);
  663.  
  664.     *pstmt = (Stmt *)stmt;
  665.     stmt->st_Func = (void (*)(void *))GenIf;
  666.     stmt->st_Tok  = TokIf;
  667.     stmt->st_LexIdx = LFBase->lf_Index;
  668.  
  669.     stmt->LabelIf   = AllocLabel();
  670.     stmt->LabelElse = AllocLabel();
  671.     stmt->LabelEnd  = AllocLabel();
  672.  
  673.     t = SkipToken(t, TokLParen);
  674.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);      /*  cond    */
  675.     /* Make sure that the expression actually returns a value */
  676.  
  677.     t = SkipToken(t, TokRParen);
  678.     t = CompStmtDeclExp(t, &stmt->StmtT, 1);      /*  true    */
  679.     if (t == TokElse)
  680.     t = CompStmtDeclExp(GetToken(), &stmt->StmtF, 1); /*  false */
  681.  
  682.     if (stmt->Stmt1->st_Tok != TokExp)
  683.     zerror(EFATAL_STMT_COND_NOT_EXP);
  684.     InsertBranch(&((ExpStmt *)stmt->Stmt1)->Expr, COND_F, stmt->LabelElse);
  685.  
  686.     return(t);
  687. }
  688.  
  689. /*
  690.  *  switch (exp) { ... }
  691.  *
  692.  *  Not only is exp in a semantic level, but each case/default is as well, so
  693.  *  you can:        case 1:
  694.  *            int i = 4;
  695.  *            ...
  696.  *            case 2:
  697.  *            int i = 5;
  698.  *            ...
  699.  *
  700.  */
  701.  
  702. short
  703. CompSwitch(short t, Stmt **pstmt)
  704. {
  705.     SwitchStmt *stmt = AllocTmpStructure(SwitchStmt);
  706.     BlockStmt *block = BlockDown(BT_SWITCH);
  707.     short siz = 0;
  708.     short haveCase = 0;
  709.  
  710.     *pstmt = (Stmt *)block;
  711.  
  712.     BlockAddStmt((Stmt *)stmt);
  713.  
  714.     stmt->st_Func = (void (*)(void *))GenSwitch;
  715.     stmt->st_Tok  = TokSwitch;
  716.     stmt->st_LexIdx = LFBase->lf_Index;
  717.  
  718.     stmt->Block = block;
  719.  
  720.     block->LabelLoop  = AllocLabel();
  721.     block->LabelBreak = AllocLabel();
  722.  
  723.     t = SkipToken(t, TokLParen);
  724.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);    /*  exp  */
  725.     Assert(stmt->Stmt1->st_Tok == TokExp);
  726.                         /*    don't deallocate result!  */
  727.     stmt->Stmt1->st_Func = (void (*)(void *))GenExpResult;
  728.  
  729.     t = SkipToken(t, TokRParen);
  730.     t = SkipToken(t, TokLBrace);
  731.  
  732.     /*
  733.      *    now, each case and default is in its own block.
  734.      */
  735.  
  736.     while (t && t != TokRBrace) {
  737.     if (t == TokCase) {
  738.         Exp *exp;
  739.  
  740.         if (siz == stmt->NumCases) {
  741.         if (siz >= 32)
  742.             siz *= 2;
  743.         else
  744.             siz += 4;
  745.         stmt->Cases = zrealloc(stmt->Cases, sizeof(stmt->Cases[0]), stmt->NumCases, siz);
  746.         stmt->Labels= zrealloc(stmt->Labels, sizeof(stmt->Labels[0]), stmt->NumCases, siz);
  747.         stmt->CaseAry = zrealloc(stmt->CaseAry, sizeof(stmt->CaseAry[0]), stmt->NumCases, siz);
  748.         }
  749.  
  750.         if (haveCase)
  751.         BlockUp();
  752.         stmt->CaseAry[stmt->NumCases] = BlockDown(BT_BLOCK);
  753.         {
  754.         long l = AllocLabel();
  755.  
  756.         stmt->CaseAry[stmt->NumCases]->LabelTest = l;
  757.         stmt->Labels[stmt->NumCases] = l;
  758.         }
  759.         t = CompExp(GetToken(), &exp, 1);
  760.         stmt->Cases[stmt->NumCases] = ExpToConstant(exp);
  761.         ++stmt->NumCases;
  762.         t = SkipToken(t, TokColon);
  763.         haveCase = 1;
  764.     } else if (t == TokDefault) {
  765.         if (haveCase)
  766.         BlockUp();
  767.         if (stmt->DefBlock)
  768.         zerror(EERROR_DUPLICATE_DEFAULT);
  769.         stmt->DefBlock = BlockDown(BT_BLOCK);
  770.         stmt->DefBlock->LabelTest = AllocLabel();
  771.         stmt->DefCaseNo = stmt->NumCases;    /*  insert before...    */
  772.  
  773.         t = SkipToken(GetToken(), TokColon);
  774.         haveCase = 1;
  775.     } else {
  776.         Stmt *caseStmt;
  777.  
  778.             if (haveCase == 0 &&
  779.                 t != TokStruct   &&
  780.                 t != TokEnum     &&
  781.                 t != TokUnion    &&
  782.                 t != TokTypeQual &&
  783.                 t != TokTypeDef  &&
  784.                 t != TokTypeId   &&
  785.                 t != TokTypeof)
  786.             {
  787.         stmt->BeforeBlock = BlockDown(BT_BLOCK);
  788.         haveCase = 1;
  789.         }
  790.  
  791.         t = CompStmtDeclExp(t, &caseStmt, 1);
  792.  
  793.         /* Handle the case where they put code before the first case statement */
  794.         BlockAddStmt(caseStmt);
  795.     }
  796.     }
  797.  
  798.     if (haveCase)
  799.     BlockUp();
  800.  
  801.     t = GetToken();
  802.  
  803.     BlockUp();
  804.  
  805.     return(t);
  806. }
  807.  
  808. /*
  809.  *  break;
  810.  */
  811.  
  812. short
  813. CompBreak(short t, Stmt **pstmt)
  814. {
  815.     BreakStmt *stmt = AllocTmpStructure(BreakStmt);
  816.  
  817.     t = SkipToken(t, TokSemi);
  818.  
  819.     *pstmt = (Stmt *)stmt;
  820.     stmt->st_Func = (void (*)(void *))GenBreak;
  821.     stmt->st_Tok  = TokBreak;
  822.     stmt->st_LexIdx = LFBase->lf_Index;
  823.     if ((stmt->BreakLabel = FindBreakLabel()) == 0)
  824.     zerror(EERROR_BREAK_OUTSIDE_LOOPSW);
  825.     return(t);
  826. }
  827.  
  828. short
  829. CompContinue(short t, Stmt **pstmt)
  830. {
  831.     ContinueStmt *stmt = AllocTmpStructure(ContinueStmt);
  832.  
  833.     t = SkipToken(t, TokSemi);
  834.  
  835.     *pstmt = (Stmt *)stmt;
  836.     stmt->st_Func = (void (*)(void *))GenContinue;
  837.     stmt->st_Tok  = TokContinue;
  838.     stmt->st_LexIdx = LFBase->lf_Index;
  839.     if ((stmt->ContLabel = FindContinueLabel()) == 0)
  840.     zerror(EERROR_CONT_OUTSIDE_LOOP);
  841.     return(t);
  842. }
  843.  
  844. /*
  845.  *  goto label;
  846.  */
  847.  
  848. short
  849. CompGoto(short t, Stmt **pstmt)
  850. {
  851.     GotoStmt *stmt = AllocTmpStructure(GotoStmt);
  852.     SemInfo *sem = NULL;
  853.  
  854.     *pstmt = (Stmt *)stmt;
  855.     stmt->st_Func = (void (*)(void *))GenGoto;
  856.     stmt->st_Tok  = TokGoto;
  857.     stmt->st_LexIdx = LFBase->lf_Index;
  858.  
  859.     switch(t) {
  860.     case TokId:
  861.     case TokVarId:
  862.     case TokEnumConst:
  863.     if ((sem = FindSymbolId(LexSym, TokLabelId)) == NULL)
  864.     {
  865.         SemanticAddTopBlock(LexSym, TokLabelId, (void *)0);
  866.         sem = FindSymbolId(LexSym, TokLabelId);
  867.     }
  868.     break;
  869.     case TokLabelId:
  870.     Assert(0);
  871.     break;
  872.     default:
  873.     zerror(EERROR_SYNTAX_ERROR_EXP);
  874.     break;
  875.     }
  876.     stmt->GotoLabel = sem;
  877.     t = GetToken();
  878.     t = SkipToken(t, TokSemi);
  879.     return(t);
  880. }
  881.  
  882. short
  883. CompLabel(short t, Stmt **pstmt)
  884. {
  885.     LabelStmt *stmt = AllocTmpStructure(LabelStmt);
  886.     SemInfo *sem;
  887.     long label;
  888.  
  889.     *pstmt = (Stmt *)stmt;
  890.     stmt->st_Func = (void (*)(void *))GenLabel;
  891.     stmt->st_Tok  = TokLabelId;
  892.     stmt->st_LexIdx = LFBase->lf_Index;
  893.  
  894.     if ((sem = FindSymbolId(LexSym, TokLabelId)) == NULL) {
  895.     label = AllocLabel();
  896.     SemanticAddTopBlock(LexSym, TokLabelId, (void *)label);
  897.     } else {
  898.     /* How can this be... We have to issue an error message because */
  899.     /* They have defined the label twice...                         */
  900.     label = (long)sem->Data;
  901.     if (label)
  902.     {
  903.         zerror(EWARN_DUPLICATE_SYMBOL, LexSym->Len, LexSym->Name);
  904.     }
  905.     else
  906.     {
  907.         label = AllocLabel();
  908.         sem->Data = (void *)label;
  909.     }
  910.     }
  911.     stmt->Label = label;
  912.     t = SkipToken(GetToken(), TokColon);
  913.  
  914.     /*
  915.      *    normally label: is bundled with a statement.  However, there are
  916.      *    a few special cases where this is not so.
  917.      */
  918.  
  919.     if (t != TokRBrace && t != TokCase && t != TokDefault)
  920.     t = CompStmtDeclExp(t, &stmt->Stmt1, 1);
  921.     return(t);
  922. }
  923.  
  924.  
  925. /*
  926.  *  return exp;
  927.  */
  928.  
  929. short
  930. CompReturn(short t, Stmt **pstmt)
  931. {
  932.     ReturnStmt *stmt = AllocTmpStructure(ReturnStmt);
  933.  
  934.     *pstmt = (Stmt *)stmt;
  935.     stmt->st_Func = (void (*)(void *))GenReturn;
  936.     stmt->st_Tok  = TokReturn;
  937.     stmt->st_LexIdx = LFBase->lf_Index;
  938.  
  939.     if (t != TokSemi) {
  940.     t = CompStmtDeclExp(t, &stmt->Stmt1, 0);    /*    exp  */
  941.     if (stmt->Stmt1->st_Tok != TokExp)
  942.         zerror(EFATAL_SYNTAX_ERROR_EXP);
  943.                             /*    save result */
  944.     stmt->Stmt1->st_Func = (void (*)(void *))GenExpResult;
  945.     }
  946.     t = SkipToken(t, TokSemi);
  947.  
  948.     return(t);
  949. }
  950.  
  951. /*
  952.  *  __breakpoint
  953.  */
  954.  
  955. short
  956. CompBreakPoint(short t, Stmt **pstmt)
  957. {
  958.     BreakPointStmt *stmt = AllocTmpStructure(BreakPointStmt);
  959.  
  960.     *pstmt = (Stmt *)stmt;
  961.     stmt->st_Func = (void (*)(void *))GenBreakPoint;
  962.     stmt->st_Tok  = TokBreakPoint;
  963.     stmt->st_LexIdx = LFBase->lf_Index;
  964.  
  965.     return(t);
  966. }
  967.  
  968.  
  969.